#ifndef __BASEWORD_H__
#define __BASEWORD_H__

#include <fstream>
#include <iostream>
#include <ostream>

#include "FieldSpecifications.h"

// defines the base for all words
class BaseWord
{
	public:
		// distinct values that can be stored in a byte
		static const unsigned short DISTINCT_BYTE_VALUES = 64;

		// destructor
		virtual ~BaseWord(void);

		// Gets the sign of the word
		signed char get_sign() const;

		// Sets the sign of the word
		void set_sign(const signed char sign);

		// Gets the size of the word
		unsigned short get_size() const;

		// Sets the value with the sign
		void value(const signed char sign, const unsigned char values[]);

		// Gets the value of the word as a signed int
		signed int value() const;

		// Sets the value without touching the sign
		void value(const unsigned char values[]);

		// Sets the value
		void value(const signed int value);

		// Gets a const point to the values array
		unsigned char* const value_bytes() const;

		// outputs the word in a human readable form
		// os: stream to write to
		void write_word(std::ostream* const os) const;

		// outputs the word in a human readable form
		// os: stream to write to
		// revertHex: indicates whether or not a hex revert is to be performed
		void write_word(std::ostream* const os, const bool revertHex) const;

		// Gets the Address Value (+/- AA)
		signed short address_value() const;

		// retries the value of the field specification
		// fieldSpecification: field specification
		signed int value_according_to_field_specification(const FieldSpecifications &fieldSpecification) const;

		// retrieves the value of the field specification of left:right
		// left: inclusive left boundary
		// right: inclusive right boundary
		signed int value_according_to_field_specification(const unsigned short left, const unsigned short right) const;

		// retrieves the value of the field specification of left:right
		// fieldSpecification: the packed field specification
		signed int value_according_to_field_specification(const unsigned short fieldSpecification) const;

		// Deserializes a word from the stream
		// fs: stream to deserialize from
		void deserialize(std::istream* const fs);

		// serializes a word to the stream
		// fs: stream to serialize to
		void serialize(std::ostream* const fs) const;

	protected:
		// constructor
		// size: size of the word
		BaseWord(const unsigned short size);

		// constructor
		// size: size of the word
		// sign: sign of the word
		// values: values for the bytes in the word
		BaseWord(const unsigned short size, const signed char sign, const unsigned char values[]);

	private:
		// size of the word
		unsigned short size;

		// actual values
		unsigned char* pValues;

		// the sign of the word (+1: positive; -1: negative; 0: undefined)
		signed char sign;

		// Initializes the word
		void initialize(unsigned short size);
};
#endif
